#pragma once

#include <opencv2/opencv.hpp>
#include "opencv2/imgcodecs/legacy/constants_c.h"
#include "opencv2/imgproc/types_c.h"

#include "utils.h"
#include "acl/acl.h"
#include "dimp/model_process.h"
#include "dimp/preprocess_for_init.hpp"
#include "dimp/dimp_init.hpp"
#include <memory>
#include <vector>

using namespace std;
using namespace cv;



/**
* ObjectDetect
*/
class Dimp_Track{
public:
    Dimp_Track(const char* model_01_path, const char* model_02_path);
    ~Dimp_Track();
    //Inference initialization
    Result Init(int32_t& deviceId, aclrtContext& context, aclrtStream& stream, aclrtRunMode& runMode);
    //nference frame image preprocessing
    Result LoadInputDataForScoreModel(cv::Mat sample_img, void* weights);
    Result LoadInputDataForIouModelOnce(void* modulation1, void* modulation2, Target_Box init_iou_box);
    Result LoadInputDataForIouModelAlways();
    Result GetOutputBox();
    //Inference frame picture
    Result InferenceForScores();
    Result InferenceForIou();
    //Inference output post-processing
    Result CreateInputdDataset_for_ScoreModel();

    Result CreateInputdDataset_for_IouModel();

    Result PostProcessForIouModel();
    void DestroyResource();

    Nodes layer2_;
    Nodes layer3_;
    Box predicted_box_;
    float predicted_iou_;

    Nodes classifier_feat_;
    Nodes iou_pred_;
    Nodes scores_;
    
private:
    //Initializes the ACL resource
    Result InitResource();
    //Loading reasoning model
    Result InitModel();

    //Establish a connection to the Presenter Server
    Result OpenPresenterChannel();
    //Get data from model inference output aclmdlDataset to local
    void* GetInferenceOutputItem(uint32_t& itemDataSize,
    aclmdlDataset* inferenceOutput,
    uint32_t idx);
    //Serializes a frame image into a data stream

    void GetIouBoxes(Target_Box init_iou_box); 

    float roiboxes_[50][5];     //用数值计算的方法求梯度
    void* roiboxesBuf_;
    uint32_t roiboxesSize_;

    double orig_[10];
    double output_deltax_[10];
    double output_deltay_[10];
    double output_deltaw_[10];
    double output_deltah_[10];




private:
    int32_t deviceId_;
    aclrtContext context_;
    aclrtStream stream_;
    ModelDimpProcess get_scores_model_;
    ModelDimpProcess get_iou_model_;

    const char* score_model_path_;
    const char* iou_model_path_;


    vector<cv::Mat> sample_img_;
    void* weightsDatabuf_;
    uint32_t size_of_weights_;
    const char* modelPath_; //Offline model file path
    uint32_t modelWidth_;   //The input width required by the model
    uint32_t modelHeight_;  //The model requires high input
    uint32_t imageDataSize_; //Model input data size
    void*    imageDataBuf_;      //Model input data cache
    aclrtRunMode runMode_;   //Run mode, which is whether the current application is running on atlas200DK or AI1
    float sampleBox_[5];
    uint32_t totalSize_;

    void* layer2DataBuf_;
    void* layer3DataBuf_;
    void* modulation1DataBuf_;
    void* modulation2DataBuf_;

    bool isInited_;     //Initializes the tag to prevent inference instances from being initialized multiple times
};
